﻿/*
 * @Autor: PK
 * @Date: 2021/12/23 16:16:SS
 */

using System;
using System.Collections.Generic;
using System.Data;
using ShkSimulation.core.dao.output.result;
using ShkSimulation.core.optimization.algorithm;
using ShkSimulation.core.optimization.extractor;
using ShkSimulation.core.optimization.extractor.result;
using ShkSimulation.core.optimization.impl;
using ShkSimulation.core.optimization.variable;
using ShkSimulation.core.template;

namespace ShkSimulation.core.optimization.interfaces {

	public interface Optimization {

		public CloneableNetwork RealNetworkTemplate { get; }

		public NamedDecisionVariableExtractor DecisionVariableExtractor { get; }
		
		public TargetVariableExtractor TargetVariableExtractor { get;set; }
		
		public OptimizationAlgorithm Algorithm { get; }
		
		public OptimizationConfig Config { get; }
		
		public ParallelUniqueIdGenerator UniqueIdGenerator { get; }
		
		public DecisionVariableConverter<double> DecisionVariableConverter { get; }
		
		public ResultEvaluationStrategy EvaluationStrategy { get; }
		
		public EvaluateResult BestOne { get; set; }
		
		public DecisionVariableVector<double> VariableVectorTemplate { get; set; }

		public Dictionary<string, double> GetOptimizedDecisionVariables() {
			return DecisionVariableExtractor.ExtractNamedDecisionVariables(GetOptimizedInput());
		}
		
		public NetworkInputData GetOptimizedInput() {
			return BestOne?.Network?.NetworkInput;
		}

		public void Optimize();
		
		public EvaluateResult RunSingleThenEvaluate(DecisionVariableVector<double> variableVector) {
			// 使用决策变量生成新的路网输入
			NetworkInputData input = RealNetworkTemplate.NetworkInput;
			Dictionary<string, double> namedValues = DecisionVariableConverter.Revert(variableVector);
			NetworkInputData newInput = DecisionVariableExtractor.CloneThenInjectNamedDecisionVariables(input, namedValues);
			// 创建路网并仿真
			int id = UniqueIdGenerator.Generate();
			Network newNetwork = RealNetworkTemplate.CloneOrCreate(id, id.ToString(), newInput);
			newNetwork.Init(Config.StartTime);
			newNetwork.RunWithTerminate(Config.SimulationTimeSpan, Config.ObserveTimeSpan);
			// 输出结果
			Result result = newNetwork.GetCurrentResult(newNetwork.UniqueId.ToString());
			Dictionary<string, double> targetVatiables = TargetVariableExtractor.ExtractNamedDecisionVariables(result);
			double valuation = EvaluationStrategy.Evaluate(targetVatiables);
			return EvaluateResult.Create(variableVector, newNetwork, valuation);
		}

	}

}